package com.demo.java.OD301_350.OD313;

import java.util.Scanner;
import java.util.Stack;

/**
 * @author bug菌
 * @Source 公众号：猿圈奇妙屋
 * @des： 【仿 LISP 运算(B卷)】问题
 * @url： https://blog.csdn.net/weixin_43970743/article/details/146105581
 */
public class OdMain {
    // 数字栈，用于存储操作中的数字
    static Stack<Integer> numStack = new Stack<>();

    // 操作符栈，用于存储操作符（add, sub, mul, div等）
    static Stack<String> operatorStack = new Stack<>();

    public static void main(String[] args) {
        // 创建扫描器用于获取输入
        Scanner sc = new Scanner(System.in);
        String input = sc.nextLine();  // 从标准输入读取整行字符串

        int index = 0;  // 索引，用于追踪数字在输入字符串中的起始位置

        // 遍历输入字符串的每个字符
        for (int i = 0; i < input.length(); i++) {
            char ch = input.charAt(i);  // 获取当前字符

            // 如果字符是左括号 '('，表示遇到一个运算符表达式
            if (ch == '(') {
                // 将运算符（括号内的前三个字符）压入操作符栈中
                operatorStack.push(input.substring(i + 1, i + 4));
                i += 4;  // 跳过这三个字符（运算符），让索引指向运算符之后的位置
                index = i + 1;  // 更新数字起始位置
            }
            // 如果字符是右括号 ')'
            else if (ch == ')') {
                // 如果括号内有数字（即上一个数字还没被处理），就处理它
                if (index < i) {
                    pushNumber(input.substring(index, i));  // 将数字压入数字栈
                    i += 1;  // 跳过右括号
                    index = i + 1;  // 更新数字起始位置
                }
                // 执行一次计算操作
                calculate();
            }
            // 如果字符是空格 ' '，表示当前数字结束
            else {
                if (ch == ' ' && index < i) {
                    // 将数字从字符串中提取并压入数字栈
                    pushNumber(input.substring(index, i));
                    index = i + 1;  // 更新数字起始位置
                }
            }
        }

        // 最后可能有未计算的操作，继续执行
        while (!operatorStack.isEmpty()) {
            calculate();
        }

        // 打印计算结果，栈中应该只剩下一个数字，就是结果
        System.out.println(numStack.get(0));
    }

    // 将字符串形式的数字转换为整数并压入数字栈
    private static void pushNumber(String number) {
        try {
            numStack.push(Integer.parseInt(number));  // 尝试将字符串转换为整数并压入栈
        } catch (NumberFormatException e) {
            handleInvalidInput();  // 如果转换失败，处理无效输入（退出程序）
        }
    }

    // 根据栈中的操作符进行计算
    private static void calculate() {
        // 弹出两个操作数和一个运算符
        int num2 = numStack.pop();
        int num1 = numStack.pop();
        String op = operatorStack.pop();

        // 根据运算符执行相应的运算
        switch (op) {
            case "add":
                numStack.push(num1 + num2);  // 加法运算
                break;
            case "sub":
                numStack.push(num1 - num2);  // 减法运算
                break;
            case "mul":
                numStack.push(num1 * num2);  // 乘法运算
                break;
            case "div":
                handleDivision(num1, num2);  // 除法运算
                break;
            default:
                handleInvalidInput();  // 如果运算符无效，处理无效输入
        }
    }

    // 处理除法运算，避免除以0的错误
    private static void handleDivision(int num1, int num2) {
        if (num2 == 0) {
            // 如果除数为0，输出错误并退出
            System.out.println("error");
            System.exit(0);  // 退出程序
        } else {
            // 否则，进行除法运算，确保按照题目要求进行取整
            int res = num1 / num2 + ((num1 % num2 != 0) ? (num1 > 0 ? 1 : -1) : 0);
            numStack.push(res);  // 将结果压入数字栈
        }
    }

    // 处理无效输入（如非法字符、无效的表达式等）
    private static void handleInvalidInput() {
        System.exit(0);  // 退出程序
    }
}
